# 导入Django模型模块
from django.db import models
# 导入Django内置用户模型
from django.contrib.auth.models import User
import uuid
# 导入模型保存信号
from django.db.models.signals import post_save
# 导入信号接收器装饰器
from django.dispatch import receiver


class LotteryData(models.Model):
    """彩票数据模型"""
    # 状态选项定义
    STATUS_CHOICES = [
        ('pending', '未开奖'),
        ('closed', '已开奖')
    ]

    # 彩票期号字段（唯一且建立索引）
    issue_number = models.CharField("期号", max_length=20, unique=True, db_index=True)
    # 开奖号码字段（默认显示等待开奖）
    numbers = models.CharField("开奖号码", max_length=100, default='等待开奖')
    # 总和值字段（默认-1表示未计算）
    sum_value = models.IntegerField("总和", default=-1)
    # 记录创建时间（自动添加时间）
    created_at = models.DateTimeField("创建时间", auto_now_add=True)
    # 彩票开始时间（自动添加时间）
    start_time = models.DateTimeField("开始时间", auto_now_add=True)
    # 状态字段（带选项和索引）
    status = models.CharField("状态", max_length=10, choices=STATUS_CHOICES, default='pending', db_index=True)

    class Meta:
        """元数据配置"""
        # 按期号降序排列
        ordering = ['-issue_number']
        # 管理界面显示名称
        verbose_name = "彩票数据"
        verbose_name_plural = "彩票数据"
        # 数据库索引配置
        indexes = [
            models.Index(fields=['issue_number', 'status']),  # 联合索引
            models.Index(fields=['-start_time'])  # 时间倒序索引
        ]

    def __str__(self):
        """对象字符串表示"""
        return f"{self.issue_number} - {self.numbers}（状态：{self.get_status_display()}）"


class UserProfile(models.Model):
    """用户扩展资料模型"""
    # 与User模型的一对一关联
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,  # 级联删除
        related_name='profile',    # 反向关联名称
        verbose_name="用户"
    )
    invite_code = models.CharField(max_length=36, unique=True, blank=True, null=True)
    # 用户积分字段（默认为10000）
    score = models.PositiveIntegerField("积分", default=10000)
    inviter = models.ForeignKey(  # 新增邀请人字段
        'self',
        on_delete=models.SET_NULL,  # 允许为空
        null=True,
        blank=True,
        related_name='invitees',
        verbose_name="邀请人"
    )
    # 资料创建时间
    created_at = models.DateTimeField("创建时间", auto_now_add=True)

    class Meta:
        """元数据配置"""
        verbose_name = "用户资料"
        verbose_name_plural = "用户资料"
        indexes = [
            models.Index(fields=['user', 'inviter']),  # 新增联合索引
        ]

    def __str__(self):
        # 修正点：通过user字段访问username
        inviter_display = self.inviter.user.username if self.inviter and self.inviter.user else '无'
        return f"{self.user.username}（积分：{self.score}，邀请人：{inviter_display})"


class BetRecord(models.Model):
    is_settled = models.BooleanField("是否已结算", default=False, db_index=True)  # 添加索引
    # 在原有BET_TYPE_CHOICES基础上追加数字类型
    BET_TYPE_CHOICES = [
        ('small', '小（0-13）'),
        ('big', '大（14-27）'),
        ('odd', '单'),
        ('even', '双'),
        ('small_odd', '小单'),
        ('small_even', '小双'),
        ('big_odd', '大单'),
        ('big_even', '大双'),
        # 新增数字类型
        ('0', '0'), ('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'),
        ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'), ('9', '9'),
        ('10', '10'), ('11', '11'), ('12', '12'), ('13', '13'),
        ('14', '14'), ('15', '15'), ('16', '16'), ('17', '17'),
        ('18', '18'), ('19', '19'), ('20', '20'), ('21', '21'),
        ('22', '22'), ('23', '23'), ('24', '24'), ('25', '25'),
        ('26', '26'), ('27', '27'),
    ]

    # 当前积分字段（下注后积分）
    current_score = models.PositiveIntegerField("下注后积分", default=0)
    # 是否取消字段
    is_cancelled = models.BooleanField(default=False)
    # 结果选项定义
    RESULT_CHOICES = [
        (True, '赢'),
        (False, '输'),
        (None, '待结算')
    ]

    # 关联用户的外键
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,  # 级联删除
        related_name='bets',       # 反向关联名称
        verbose_name="用户"
    )
    # 彩票期号字段（建立索引）
    issue = models.CharField("期号", max_length=20, db_index=True)
    # 投注类型字段
    bet_type = models.CharField("下注类型", max_length=10, choices=BET_TYPE_CHOICES)
    # 投注金额字段
    amount = models.PositiveIntegerField("金额")
    # 结果字段（允许空值并建立索引）
    result = models.BooleanField("结果", choices=RESULT_CHOICES, null=True, db_index=True)
    # 投注时间字段（自动添加时间）
    created_at = models.DateTimeField("下注时间", auto_now_add=True)

    class Meta:
        """元数据配置"""
        ordering = ['-created_at']  # 按时间降序排列
        verbose_name = "下注记录"
        verbose_name_plural = "下注记录"
        indexes = [
            models.Index(fields=['user', 'result']),  # 联合索引
            models.Index(fields=['-created_at'])      # 时间倒序索引
        ]

    def get_result_display(self):
        """获取结果的可读显示"""
        return dict(self.RESULT_CHOICES).get(self.result)


@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        # 生成唯一邀请码
        invite_code = uuid.uuid4().hex[:8]  # 8位随机字符串
        # 确保唯一性
        while UserProfile.objects.filter(invite_code=invite_code).exists():
            invite_code = uuid.uuid4().hex[:8]
        UserProfile.objects.create(user=instance, invite_code=invite_code)


@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    if hasattr(instance, 'profile'):
        instance.profile.save()